package org.ru.mse10.cvis.web.bean.action.search;

import java.io.StringWriter;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.ru.mse10.cvis.dto.cv.CvSearchDTO;
import org.ru.mse10.cvis.entity.cv.CvData;
import org.ru.mse10.cvis.entity.search.CVSearchCriteria;
import org.ru.mse10.cvis.service.CvService;
import org.ru.mse10.cvis.service.JobTimerService;
import org.ru.mse10.cvis.service.search.CVSearcher;
import org.ru.mse10.cvis.service.search.EntitySearcher;
import org.ru.mse10.cvis.web.bean.action.CvAction;
import org.ru.mse10.cvis.web.bean.action.search.datamodel.JPADataModel;

/**
 * The Class CVSearchAction.
 * 
 * @author Spawn
 */
@SessionScoped
@ManagedBean(name = "searchCV")
public class CVSearchAction extends
		BasesSearchAction<CvService, CvData, CvSearchDTO> {

	/** The cv service. */
	@EJB
	private CvService cvService;

	/** The cv action. */
	@ManagedProperty("#{cvAction}")
	private CvAction cvAction;

	/** The job timer service. */
	@EJB
	private JobTimerService jobTimerService;

	/** The show save search. */
	private boolean showSaveSearch;

	/** The empty search. */
	private boolean emptySearch;

	/** The search criteria. */
	private CVSearchCriteria searchCriteria = new CVSearchCriteria();

	/**
	 * The Class CvSearchDataModel.
	 */
	private class CvSearchDataModel extends
			JPADataModel<CvService, CvData, CvSearchDTO> {

		/** The dto. */
		private final CvSearchDTO dto;

		/** The searcher. */
		private final CVSearcher searcher;

		/**
		 * Instantiates a new cv search data model.
		 * 
		 * @param dto
		 *            the dto
		 */
		public CvSearchDataModel(CvSearchDTO dto) {
			this.dto = dto;
			this.searcher = new CVSearcher();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.ru.mse10.cvis.web.bean.action.search.datamodel.JPADataModel#
		 * getSearcher()
		 */
		@Override
		public EntitySearcher<CvData, CvSearchDTO> getSearcher() {
			return searcher;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.ru.mse10.cvis.web.bean.action.search.datamodel.JPADataModel#
		 * getService()
		 */
		@Override
		public CvService getService() {
			return CVSearchAction.this.getService();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.ru.mse10.cvis.web.bean.action.search.datamodel.JPADataModel#getDto
		 * ()
		 */
		@Override
		public CvSearchDTO getDto() {
			return dto;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.ru.mse10.cvis.web.bean.action.search.datamodel.JPADataModel#
		 * getEntityClass()
		 */
		@Override
		public Class<CvData> getEntityClass() {
			return CvData.class;
		}

	}

	/**
	 * Create CV search... render web page.
	 * 
	 * @return - string linked with jsf page
	 */
	public String createCVSearch() {
		setDataModel(null);
		return "searchCV";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.ru.mse10.cvis.web.bean.action.search.BasesSearchAction#
	 * previewSearchResult()
	 */
	@Override
	public String previewSearchResult() {
		return cvAction.loadForPreview(cvService.find(CvData.class,
				getSelectedId()));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.ru.mse10.cvis.web.bean.action.search.BasesSearchAction#getService()
	 */
	@Override
	public CvService getService() {
		return cvService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.ru.mse10.cvis.web.bean.action.search.BasesSearchAction#createDataModel
	 * (org.ru.mse10.cvis.dto.BaseDTO)
	 */
	@Override
	public JPADataModel<CvService, CvData, CvSearchDTO> createDataModel(
			CvSearchDTO dto) {
		return new CvSearchDataModel(dto);
	}

	/**
	 * Method that will save search to database like string and we can use it
	 * later to repeat the search.
	 */
	public void saveSearch() {
		try {
			JAXBContext jaxbContext = JAXBContext
					.newInstance(CvSearchDTO.class);
			Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			StringWriter writer = new StringWriter();
			if (isEmptySearch()) {
				jaxbMarshaller.marshal(getDataModel().getDto(), writer);
				searchCriteria.setCriteria(writer.toString());
				cvService.saveInNewTx(searchCriteria);
			}
			jobTimerService.createJob(searchCriteria);
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Method that start searching using dto.
	 * 
	 * @param args
	 *            the args
	 */
	@Override
	public void actionSearch(CvSearchDTO args) {
		super.actionSearch(args);
		setShowSaveSearch(true);
		if (getDataModel().getDto().isEmptyOrNull()) {
			setEmptySearch(true);
		} else {
			setEmptySearch(false);
		}
	}

	/**
	 * Get method for CVSearchCriteria.
	 * 
	 * @return - current CVSearchCriteria
	 */
	public CVSearchCriteria getCriteria() {
		return searchCriteria;
	}

	/**
	 * Set method for CVSearchCriteria.
	 * 
	 * @param searchCriteria
	 *            - the current criteria
	 */
	public void setCriteria(CVSearchCriteria searchCriteria) {
		this.searchCriteria = searchCriteria;
	}

	/**
	 * Get method for showSaveSearch, which is used to display save search
	 * button only if we make search first.
	 * 
	 * @return - true or false
	 */
	public boolean isShowSaveSearch() {
		return showSaveSearch;
	}

	/**
	 * Set method for showSaveSearch.
	 * 
	 * @param showSaveSearch
	 *            - true or false
	 */
	public void setShowSaveSearch(boolean showSaveSearch) {
		this.showSaveSearch = showSaveSearch;
	}

	/**
	 * Get method for emptySearch, which is used to display save button in
	 * popupPanel only if searching have arguments.
	 * 
	 * @return - true or false
	 */
	public boolean isEmptySearch() {
		return emptySearch;
	}

	/**
	 * Set method for emptySearch.
	 * 
	 * @param emptySearch
	 *            - true or false
	 */
	public void setEmptySearch(boolean emptySearch) {
		this.emptySearch = emptySearch;
	}

	/**
	 * Gets the cv action.
	 * 
	 * @return the cv action
	 */
	public CvAction getCvAction() {
		return cvAction;
	}

	/**
	 * Sets the cv action.
	 * 
	 * @param cvAction
	 *            the new cv action
	 */
	public void setCvAction(CvAction cvAction) {
		this.cvAction = cvAction;
	}
}
